package online.inote.naruto.api.access.admin.modules.system.service;

import online.inote.naruto.api.access.admin.modules.system.entity.ManagerEntity;
import online.inote.naruto.api.access.admin.modules.system.entity.SystemEntity;
import online.inote.naruto.api.access.admin.modules.system.repository.SystemRepository;
import online.inote.naruto.api.access.jwt.JwtHelper;
import online.inote.naruto.api.access.props.ApiAccessProperties;
import online.inote.naruto.cache.CacheSupport;
import online.inote.naruto.common.utils.response.ExtendResponse;
import online.inote.naruto.common.utils.response.Response;
import online.inote.naruto.utils.DateTimeUtils;
import online.inote.naruto.utils.Page;
import online.inote.naruto.utils.StringUtils;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @description 系统服务Service
 * @author XQF.Sui
 * @date 2021/07/27 17:52
 */
@Service
@Transactional(rollbackFor = RuntimeException.class)
public class SystemService {

  private final ApiAccessProperties apiProps;
  private final SystemRepository repository;
  private final ManagerService managerService;

  public SystemService(
      ApiAccessProperties apiProps, SystemRepository repository, ManagerService managerService) {
    this.apiProps = apiProps;
    this.repository = repository;
    this.managerService = managerService;
  }

  public Response<String> save(SystemEntity system, boolean isSaveManager) {
    if (Objects.isNull(system.getCreateTime())) {
      system.setCreateTime(DateTimeUtils.getNow());
    }

    system.genSignatureDigest();

    if (apiProps.getDatabase().getEnable()) {
      repository.save(system);
    }

    if (isSaveManager) {
      managerService.save(system);
    }

    enableSystemCacheHandle(system);

    return ExtendResponse.success();
  }

  private void enableSystemCacheHandle(SystemEntity system) {
    if (system.getEnable()) {
      // 保存到cache

      String token =
          JwtHelper.genToken(
              system.getId(), system.getName(), initGenTokenMap(system), system.getCreateTime());

      if (Objects.isNull(system.getExpireTime())) {
        CacheSupport.cache(apiProps.getCache().initSystemTokenCacheKey(system.getId()), token);
      } else {
        CacheSupport.cache(
            apiProps.getCache().initSystemTokenCacheKey(system.getId()),
            token,
            DateTimeUtils.afterNowSeconds(system.getExpireTime()));
      }
    } else {
      CacheSupport.delete(apiProps.getCache().initSystemTokenCacheKey(system.getId()));
    }

    //    apiService.enableSystemCacheHandle(system);
  }

  /**
   * @description 根据系统ID查询系统详情
   * @author XQF.Sui
   * @date 2021/7/27 18:12
   * @param id 系统ID
   * @reutrn online.inote.naruto.security.admin.modules.system.entity.SystemEntity
   */
  public SystemEntity details(String id) {
    Optional<SystemEntity> optional = info(id);

    if (!optional.isPresent()) {
      return null;
    }

    SystemEntity system = optional.get();

    system.setToken(
        JwtHelper.genToken(
            system.getId(), system.getName(), initGenTokenMap(system), system.getCreateTime()));

    system.setManager(managerService.getBySystemId(system.getId()));

    system.setAuthInterfaceNumber(
        CacheSupport.count(
            apiProps.getCache().initSystemAuthInterfacePathCacheKey(system.getId())));

    return system;
  }

  private Map<String, Object> initGenTokenMap(SystemEntity system) {
    Map<String, Object> paramMap = new HashMap<>(1);
    paramMap.put(SystemEntity.Fields.englishName, system.getEnglishName());

    return paramMap;
  }

  public Optional<SystemEntity> info(String id) {
    return repository.findById(id);
  }

  /**
   * 分页
   *
   * @param page 分页信息
   */
  public void getPage(Page<SystemEntity> page) {
    Example<SystemEntity> example;

    if (Objects.nonNull(page.getSearchParams())) {
      example = Example.of(page.getSearchParams());
    } else {
      example = Example.of(new SystemEntity());
    }

    Sort sort = Sort.by(SystemEntity.Fields.createTime).descending();
    PageRequest request = PageRequest.of(page.getEsPage(), page.getRows(), sort);
    org.springframework.data.domain.Page<SystemEntity> resultPage =
        repository.findAll(example, request);

    page.setRecords(resultPage.getTotalElements());
    page.setDataList(resultPage.getContent());

    if (CollectionUtils.isEmpty(page.getDataList())) {
      return;
    }

    List<String> idList =
        page.getDataList().stream().map(SystemEntity::getId).collect(Collectors.toList());

    List<ManagerEntity> managerList = managerService.getManagerBySystemIdList(idList);

    Map<String, ManagerEntity> managerMap =
        managerList.stream()
            .collect(Collectors.toMap(ManagerEntity::getSystemId, manager -> manager));

    page.getDataList()
        .forEach(
            system -> {
              system.setManager(managerMap.get(system.getId()));
              system.setAuthInterfaceNumber(
                  CacheSupport.count(
                      apiProps.getCache().initSystemAuthInterfacePathCacheKey(system.getId())));

              if (StringUtils.isNotBlank(page.getSearchParams().getApiId())) {
                system.setIsAuth(
                    CacheSupport.isMember(
                        apiProps
                            .getCache()
                            .initInterfaceAuthSystemCacheKey(page.getSearchParams().getApiId()),
                        system.getId()));
              }
            });
  }
}
